{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# numpy基础入门 ——by 黑板客"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. 矩阵的创建"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 2 3 5] int32 (4,) 4 1\n",
      "1\n",
      "2\n",
      "3\n",
      "4\n"
     ]
    }
   ],
   "source": [
    "# a=np.arange(1,5)\n",
    "a=np.array([1,2,3,5])\n",
    "print(a, a.dtype, a.shape, a.size, a.ndim)\n",
    "for i in range(1, 5):\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "    np.arange类似range函数\n",
    "    np.array用来生成矩阵\n",
    "    dtype是数据类型，有int64, complex, uint16等\n",
    "    shape是个元组属性，表示每一维的宽度\n",
    "    size是所有元素个数\n",
    "    ndim是维数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 1.  2.  3.] float16\n"
     ]
    }
   ],
   "source": [
    "b=np.array([1,2,3],dtype='float16') # int64, complex, uint16......\n",
    "print(b, b.dtype)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0 1 2 3 4 5]\n",
      " [0 1 2 3 4 5]] (2, 6) 12 2\n"
     ]
    }
   ],
   "source": [
    "m=np.array([np.arange(6),np.arange(6)])\n",
    "print(m, m.shape, m.size, m.ndim)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2 3 4]\n",
      " [5 6 7 8]] 3 6\n",
      "(2, 2, 3)\n"
     ]
    }
   ],
   "source": [
    "# 每一个[]代表一维，比如\n",
    "# [[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]], 代表矩阵的维度是(2,2,3)\n",
    "# 其中第一个2，代表最外层的两个[]，第二个2代表第二层[]，第三个3代表最里层的维度。\n",
    "n=np.array([[1,2,3,4],[5,6,7,8]])\n",
    "print(n, n[0,2], n[1,1])\n",
    "\n",
    "m=np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])\n",
    "print(m.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 1  2  3 10  5  6  7  8  9 10 11 12]\n",
      "[1 2 3 4 5 6 7 8]\n"
     ]
    }
   ],
   "source": [
    "x=m.ravel()\n",
    "y=n.flatten()\n",
    "print(x)\n",
    "print(y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "    ravel()和flatten()看起来效果一样，都是把矩阵展平了。它们的区别在于\n",
    "    ravel()返回的是原有数据的一个映射(view)，没有分配新的存储\n",
    "    flatten()返回的是新的数据\n",
    "    因此如果我们改变它们的值，就可以看出区别\n",
    "    \n",
    "    numpy还有一些函数有这样的区别，关键在于判断函数返回是原数据的映射还是返回新的数据。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[[ 1  2  3]\n",
      "  [10  5  6]]\n",
      "\n",
      " [[ 7  8  9]\n",
      "  [10 11 12]]]\n",
      "[[1 2 3 4]\n",
      " [5 6 7 8]]\n"
     ]
    }
   ],
   "source": [
    "x[3]=10;y[3]=10\n",
    "print(m)\n",
    "print(n)\n",
    "# 看看m，n哪个的值改变了"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 1  2  3 10]\n",
      " [ 5  6  7  8]\n",
      " [ 9 10 11 12]] None \n",
      " [[1 2 3 4]\n",
      " [5 6 7 8]\n",
      " [0 0 0 0]]\n"
     ]
    }
   ],
   "source": [
    "# reshape返回一个view\n",
    "x=m.reshape(3,4)\n",
    "# resize直接在当前数据上更改，返回空\n",
    "y=n.resize(3,4)\n",
    "print(x,y,'\\n',n)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 1  2  3 10]\n",
      " [ 5  6  7  8]\n",
      " [10 10 10 10]]\n",
      "[[[ 1  2  3]\n",
      "  [10  5  6]]\n",
      "\n",
      " [[ 7  8 10]\n",
      "  [10 10 10]]]\n"
     ]
    }
   ],
   "source": [
    "x[2]=10;print(x);print(m)\n",
    "# 看看m和n哪个改变了，有什么区别"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0  1  2  3]\n",
      " [ 4  5  0  1]\n",
      " [10 10 10 10]]\n",
      "[[0 1 2 3 4 5]\n",
      " [0 1 2 3 4 5]]\n"
     ]
    }
   ],
   "source": [
    "m=np.array([np.arange(6),np.arange(6)])\n",
    "# copy()可以强制返回一个新的数据\n",
    "x=m.reshape(3,4).copy()\n",
    "x[2]=10;print(x);print(m)\n",
    "#看看这次m的值随x改变而改变吗"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 0.          0.11111111  0.22222222  0.33333333  0.44444444  0.55555556\n",
      "  0.66666667  0.77777778  0.88888889  1.        ]\n"
     ]
    }
   ],
   "source": [
    "# linspace返回0,1之间的10个数据，它们之间的间隔自动计算\n",
    "x=np.linspace(0,1,10)\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[6 5 3 8 0 9 1 2 4 7]\n",
      "[[6 7 8]\n",
      " [3 4 5]\n",
      " [0 1 2]]\n"
     ]
    }
   ],
   "source": [
    "a = np.arange(10)\n",
    "np.random.shuffle(a)  # 随机排第一维\n",
    "print(a)\n",
    "\n",
    "a = np.arange(9).reshape((3, 3)) # 随机排第一维，想一想结果是什么\n",
    "np.random.shuffle(a)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# 全0矩阵\n",
    "a=np.zeros((3,3))\n",
    "# 全1矩阵\n",
    "b=np.ones((5,4))\n",
    "# 单位矩阵\n",
    "c=np.eye(3)\n",
    "# 取对角元素\n",
    "np.diag(b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. 矩阵的加法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0 1 2]\n",
      " [3 4 5]\n",
      " [6 7 8]]\n",
      "[[ 3  4  5]\n",
      " [ 6  7  8]\n",
      " [ 9 10 11]]\n",
      "[[ 0  2  4]\n",
      " [ 3  5  7]\n",
      " [ 6  8 10]]\n",
      "[[ 0  1  2]\n",
      " [ 4  5  6]\n",
      " [ 8  9 10]]\n"
     ]
    }
   ],
   "source": [
    "a = np.arange(9).reshape((3, 3))\n",
    "\n",
    "## 每个元素的broadcast\n",
    "print a\n",
    "print a+3\n",
    "\n",
    "## 行broadcast\n",
    "print a+np.arange(3)\n",
    "\n",
    "## 列broadcast\n",
    "print a+np.arange(3).reshape(3,1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "    broadcast广播操作\n",
    "    运算不仅仅作用在某个元素，而是作用在整个矩阵，或者整行，或者整列。\n",
    "    比如\n",
    "    n*m + 1*1 就是将1*1的元素作用在n*m的整个矩阵\n",
    "    n*m + n*1 就是将n*1的元素作用在n*m的每一列\n",
    "    n*m + 1*m 就是将1*m的元素作用在n*m的每一行\n",
    "    乘法类似"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[4 6]\n",
      "[3 7]\n",
      "[ 2.  3.]\n",
      "[ 1.5  3.5]\n",
      "[ 1.  1.]\n"
     ]
    }
   ],
   "source": [
    "a = np.array([[1, 2], [3, 4]])\n",
    "print(np.sum(a,axis=0))\n",
    "print(np.sum(a,axis=1))\n",
    "print(np.mean(a,axis=0))\n",
    "print(np.mean(a,axis=1))\n",
    "print(np.std(a,axis=0))\n",
    "\n",
    "#axis=0，就是按第一个维度进行计算，行向量[1,2], [3,4]\n",
    "#axis=1，就是按第二个维度进行计算，列向量[1,3], [2,4]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 6  8 10]\n",
      " [12 14 16]]\n",
      "[[ 3  5  7]\n",
      " [15 17 19]]\n",
      "[[ 3 12]\n",
      " [21 30]]\n"
     ]
    }
   ],
   "source": [
    "#再拓展到3维\n",
    "a = np.arange(12).reshape((2,2,3))\n",
    "print(np.sum(a,axis=0)) #按第一维度加，结果为2*3矩阵, 可以理解为1*2*3\n",
    "print(np.sum(a,axis=1)) #按第二维度加，结果为2*3矩阵, 可以理解为2*1*3\n",
    "print(np.sum(a,axis=2)) #按第三维度加，结果为2*2矩阵, 可以理解为2*2*1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. 矩阵的转置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0 0]\n",
      " [1 1]\n",
      " [2 2]\n",
      " [3 3]\n",
      " [4 4]\n",
      " [5 5]]\n",
      "[[0 0]\n",
      " [1 1]\n",
      " [2 2]\n",
      " [3 3]\n",
      " [4 4]\n",
      " [5 5]]\n"
     ]
    }
   ],
   "source": [
    "print(m.transpose())\n",
    "print(m.T)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. 矩阵的乘法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[  5   6   7   8   9]\n",
      " [ 15  20  25  30  35]\n",
      " [ 25  34  43  52  61]\n",
      " [ 35  48  61  74  87]\n",
      " [ 45  62  79  96 113]\n",
      " [ 55  76  97 118 139]]\n",
      "[[  5   6   7   8   9]\n",
      " [ 15  20  25  30  35]\n",
      " [ 25  34  43  52  61]\n",
      " [ 35  48  61  74  87]\n",
      " [ 45  62  79  96 113]\n",
      " [ 55  76  97 118 139]]\n"
     ]
    }
   ],
   "source": [
    "a = np.arange(12).reshape((6, 2))\n",
    "b = np.arange(10).reshape((2,5))\n",
    "\n",
    "# 两种矩阵乘法形式\n",
    "print(a.dot(b))\n",
    "print(np.dot(a,b))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0  2]\n",
      " [ 4  6]\n",
      " [ 8 10]\n",
      " [12 14]\n",
      " [16 18]\n",
      " [20 22]]\n"
     ]
    }
   ],
   "source": [
    "## 每个元素broadcast\n",
    "print(a*2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0  2]\n",
      " [ 2  6]\n",
      " [ 4 10]\n",
      " [ 6 14]\n",
      " [ 8 18]\n",
      " [10 22]]\n"
     ]
    }
   ],
   "source": [
    "# 行broadcast\n",
    "print(a*[1,2])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0  1]\n",
      " [ 2  3]\n",
      " [ 4  5]\n",
      " [ 6  7]\n",
      " [ 8  9]\n",
      " [10 11]]\n",
      "[[0]\n",
      " [1]\n",
      " [2]\n",
      " [3]\n",
      " [4]\n",
      " [5]]\n",
      "[[ 0  0]\n",
      " [ 2  3]\n",
      " [ 8 10]\n",
      " [18 21]\n",
      " [32 36]\n",
      " [50 55]]\n"
     ]
    }
   ],
   "source": [
    "# 列broadcast\n",
    "print(a)\n",
    "print(np.arange(6).reshape(6,1))\n",
    "print(a*np.arange(6).reshape(6,1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5.矩阵的拼接"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0  1  2  0  2  4]\n",
      " [ 3  4  5  6  8 10]\n",
      " [ 6  7  8 12 14 16]]\n"
     ]
    }
   ],
   "source": [
    "a = np.arange(9).reshape(3,3)\n",
    "b = 2 * a\n",
    "c = np.hstack((a, b))\n",
    "print(c)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0  1  2  0  2  4]\n",
      " [ 3  4  5  6  8 10]\n",
      " [ 6  7  8 12 14 16]]\n"
     ]
    }
   ],
   "source": [
    "print(np.concatenate((a, b), axis=1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[array([[0],\n",
      "       [3],\n",
      "       [6]]), array([[1],\n",
      "       [4],\n",
      "       [7]]), array([[2],\n",
      "       [5],\n",
      "       [8]])]\n",
      "[array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]\n"
     ]
    }
   ],
   "source": [
    "c=np.vstack((a, b))\n",
    "c=np.concatenate((a, b), axis=0)\n",
    "\n",
    "print(np.hsplit(a, 3))\n",
    "print(np.vsplit(a,3))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. 矩阵的查找"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ True False  True False]\n",
      " [ True False  True False]\n",
      " [ True False  True False]]\n",
      "[[False False False False]\n",
      " [False  True  True  True]\n",
      " [ True  True  True  True]]\n"
     ]
    }
   ],
   "source": [
    "a = np.arange(12).reshape((3, 4))\n",
    "b = a%2==0\n",
    "c = a>4\n",
    "print(b)\n",
    "print(c)\n",
    "# 这里也用到了broadcast"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0  1  2  3]\n",
      " [ 4  5  6  7]\n",
      " [ 8  9 10 11]]\n",
      "11\n",
      "[2 2 2 2]\n",
      "[3 3 3]\n"
     ]
    }
   ],
   "source": [
    "a = np.arange(12).reshape((3, 4))\n",
    "print(a)\n",
    "print(np.argmax(a))\n",
    "# 其实是列broadcast，返回每列最大值的idx\n",
    "print(np.argmax(a, axis=0))\n",
    "\n",
    "# 行broadcast，返回每行最大值的idx\n",
    "print(np.argmax(a, axis=1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 4  5  6  7  8  9 10 11]\n",
      "[4 5 6]\n"
     ]
    }
   ],
   "source": [
    "# np.where支持多个逻辑组合, 得到满足条件的index\n",
    "idx=np.where((a>3))\n",
    "print(a[idx])\n",
    "\n",
    "idx=np.where((a>3)&(a<7))\n",
    "print(a[idx])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7. homework"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. http://www.labri.fr/perso/nrougier/teaching/numpy.100/"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
